make this a question! How do Emergency Contraceptive Pill Prescribing Patterns very in Scotland?

Mark scheme: Justified – understanding of the data and their context
Introduction
Key results
Conclusion References (for reason chosen research question)
Narrative shows critical thinking
Multiple data sources
Recommendations and conclusions are grounded in the data
Limitations of the data set discussed. Next steps suggested in terms of data that would allow for further analysis.

Introduction

There are two types of emergency contraceptive pill prescribed by pharmacies.

  • Levonogestrel (brand name: Levonelle) taken within three days of unprotected sex
  • Ulipristal Acetate (brand name: ellaOne) taken within five days of unprotected sex

This report explores

  1. Prescribing patterns of emergency contraceptive pill (ECP) between 2019 to 2023.

  2. How ECP and antibiotics for STI prescriptions differ in geography comparing university town to a non-university town

  3. Compare patterns in ECP and STI antibiotics prescribing during Covid-19 lockdowns - did the need for ECP or incidence of STI antibiotics prescription go down during lockdowns?

  4. How does SIMD relate to prescription of ECP / antibiotics for STIs

# load necessary libraries
library(tidyverse)
library(janitor) 
library(gt) 
library(here)
library(lubridate)
library(sf)
library(ggspatial)
library(plotly)

I have chosen to look at all prescriptions from 2019 and 2022. To do this I downloaded the prescriptions data for each month from: https://www.opendata.nhs.scot/dataset/prescriptions-in-the-community

I wanted to explore how many ECP and antibiotics for STIs were prescibed during across 2023.

4 plots and / or tables No use of settings other than default Labelled, titled plots Labelled titled tables Appropriate and thoughtful data visualisation with some use of non-default settings (gt) Faceting, multilayered plots, interactive visualisation

Read in data:

# Read in the Health Board names (HB_names). See code for link
HB_names <- read_csv("https://www.opendata.nhs.scot/dataset/9f942fdb-e59e-44f5-b534-d6e17229cc7b/resource/652ff726-e676-4a20-abda-435b98dd7bdc/download/hb14_hb19.csv") %>% 
  clean_names() # ensures column names are unique, lower case and replaces spaces and special characters with underscores. I will use this function for all read ins to ensure my data is consistent and easy to manipulate.


# Read in population data per Health Board from the 2022 census data. Available from: https://statistics.ukdataservice.ac.uk/dataset/scotland-s-census-2022-uv102a-age-by-sex/resource/b2d295c2-af53-4b3d-a075-7815cadd9060 
all_population_data <- read_csv(here("data", "UV103_age_health_board_census.csv"), skip = 10) %>% # locates the csv and excludes the first 10 lines in the csv as they are redundant
  rename(Spare = "...6", # remove unused columns
         hb_name = "Health Board Area 2019",
         hb_population = Count) %>% # rename() formats the data to match the prescriptions dataframe
  filter(Sex == "Female") %>% # filter female population, as men do not take ECP
  select(hb_name, Age, hb_population) %>% # select columns of interest
  mutate(hb_name = paste("NHS", hb_name)) %>%  # change hb_name column format to match the Health Board dataframe format
  clean_names()

# create dataset with total population for each health board
population_data <- all_population_data %>% 
  filter(age == "All people") %>% 
  select(hb_name, hb_population)

# select the population aged 16 to 34 years as this is the population the population most likely engaging with risk taking behaviors such as unprotected sex. I chose 16 as this is the age of consent in Scotland, and 34 as my cut off for young adults. 
age_population_data <- all_population_data %>% 
  filter(age%in% c(16:34)) %>% # filter ages of interest
  mutate(age = as.numeric(age)) %>% # make numerical so they can be placed in to buckets
  mutate(age_group = case_when(between(age, 16,34)~'16-34')) %>% # make bucket 16-34 years
  group_by(hb_name, age_group) %>% 
  summarise(pop_hb_16_34 = sum(hb_population)) # sum total population aged 16 to 34 per health board region. 

Define a function to read in the prescription data for a defined year:

# #For efficiency I created a function to read in my prescriptions datasets.
# #I downloaded 12 months of prescription data for each year from 2019 to 2022. I placed the 12 months of data into their relevant folder named all_months_year, where year was specific to the data it contained.
# read_all_prescriptions <- function(year){
#   all_files <- list.files(here("data", paste0("all_months_", year)), pattern = "csv") #list.files() retrieves files from the relevant directory, and the paste0() dynamically constructs the folder name based on the year variable placed into the function.
#   all_prescriptions <- all_files %>%
#     map_dfr(~read_csv(here("data", paste0("all_months_", year),.))) %>% #map_dfr() row-binds the datasets being red in
#     clean_names() %>%
#     drop_na(bnf_item_description) # drop the rows with missing bnf_item values
#   return(all_prescriptions)
# }

Read in datasets using read_all_prescriptions() function and start tidying:

# all_prescriptions_2019 <- read_all_prescriptions(2019)
# all_prescriptions_2020 <- read_all_prescriptions(2020)
# all_prescriptions_2021 <- read_all_prescriptions(2021)
# all_prescriptions_2022 <- read_all_prescriptions(2022)
# 
# # 2019 dataset has hbt2014 as a column name instead of hbt. Rename to make column name consistent
# all_prescriptions_2019 <- all_prescriptions_2019 %>%
#   rename(hbt = "hbt2014")
# 
# # combine 4 years of data into one dataset to make it easier to wrangle
# combined_prescriptions <- bind_rows(
#   all_prescriptions_2019,
#   all_prescriptions_2020,
#   all_prescriptions_2021,
#   all_prescriptions_2022 )%>% # I mutate early and select the prescriptions of interest to prevent a very large dataset from being stored in my environment (prevents R slowing down and crashing)
#   mutate(
#     date = parse_date_time(paid_date_month, "ym"), # use lubridate to format date
#     drug_simple = case_when(
#       str_detect(bnf_item_description, "LEVONO") ~ "Levonorgestrel",
#       str_detect(bnf_item_description, "ULIPR") ~ "Ulipristal Acetate",
#       TRUE ~ "Other")) %>% # used case_when() to group different dosages of the same drug
#   filter(drug_simple != "Other",!is.na(date)) %>% #remove prescriptions of no interest and any missing date values
#   filter(hbt != "SB0806") %>% # filter out SB0806 as it is not a health board (Scottish Ambulance Service)
#   filter(!is.na(hbt))

# # save combined_prescriptions dataset to csv
# # write_csv(combined_prescriptions,"data/combined_prescriptions.csv")

# filter drugs of intereset before completing read in to prevent loading large datasets into the environment (prevents R from running slow and crashing)
combined_prescriptions <- read_csv(here("data","combined_prescriptions.csv")) %>%
  mutate(
    date = parse_date_time(paid_date_month, "ym"), # use lubridate to format date
    drug_simple = case_when(
      str_detect(bnf_item_description, "LEVONO") ~ "Levonorgestrel",
      str_detect(bnf_item_description, "ULIPR") ~ "Ulipristal Acetate",
      TRUE ~ "Other")) %>% # used case_when() to group different dosages of the same drug
  filter(drug_simple != "Other",!is.na(date))%>%  # remove other prescriptions from the dataset and any missing date values
  filter(hbt != "SB0806") %>% # filter out SB0806 as it is not a health board (Scottish Ambulance Service)
  filter(!is.na(hbt))

Join and wrangle data:

# join the Prescriptions dataset to the Health Board names dataset and health board population data
ECP_scripts <- combined_prescriptions %>% 
  full_join(HB_names, by = c("hbt" = "hb")) %>% # Join with Health Board names
  full_join(population_data, by = "hb_name") %>% # Join with population data
  select(gp_practice, date, drug = drug_simple, hb_name, paid_quantity,hb_population) %>%  # select columns of interest
  mutate(month = factor(month(date), levels = 1:12, labels = month.abb), .after = date) %>%   # extract month as a factor with labels to help when plotting
  mutate(year = factor(year(date)), .after = month) 

Key Results

Which Health Board is prescribing the most ECP?

to see if there is a trend between rate of prescribing of ECP and proportion of young people living in the HB

# tidy data to make table with columns and values of interest 
ECP_anual_rate_data <- ECP_scripts %>% 
  group_by(hb_name, drug) %>%  # aggregate data by Health Board and drug
  summarise(total_quantity_4_years = sum(paid_quantity, na.rm = TRUE),  # Total prescriptions over 4 years
    avg_annual_total_quantity = total_quantity_4_years / 4,  # average annual prescriptions
    hb_population = first(hb_population), # hb_population is consistent within each hb_name
    .groups = "drop") %>% # ungroup data
  drop_na(drug) %>% # remove rows with no drug values
  mutate(avg_annual_presc_100000 = avg_annual_total_quantity * 100000 / hb_population) %>% # average annual rate of prescriptions per 100,000
  select(hb_name, drug, avg_annual_presc_100000, hb_population) %>% # select columns of interest before pivot
  pivot_wider(names_from = drug, values_from = avg_annual_presc_100000, names_glue = "{drug}_rate") %>% # Rename columns for clarity
  clean_names() # clean column names following pivot

# calculate total ECP prescription rate per health board
ECP_anual_rate_data <- ECP_anual_rate_data %>% 
  mutate(total_ECP_rate = rowSums(select(., levonorgestrel_rate, ulipristal_acetate_rate), na.rm = TRUE)) %>%  #sum rates 
  arrange(desc(total_ECP_rate)) # arrange by total rate in descending order

#calculate percentage young people per health board 
ECP_anual_rate_data_buckets <- ECP_anual_rate_data %>% 
  full_join(age_population_data) %>% # to get the population of those aged 16-34 years 
  group_by(hb_name) %>% 
  mutate(prop_young_ppl_hb = pop_hb_16_34/hb_population) %>% # calculate proportion of young people in each health board 
  ungroup()

annual_avg_ECP_table <- ECP_anual_rate_data_buckets %>% 
  select(hb_name, levonorgestrel_rate, ulipristal_acetate_rate, total_ECP_rate,prop_young_ppl_hb) %>% # Select relevant columns
  gt() %>% 
  cols_label(hb_name = "Health Board",
             total_ECP_rate= "Total",
             levonorgestrel_rate= " Levonorgestrel",
             ulipristal_acetate_rate=" Ulipristal Acetate",
             prop_young_ppl_hb = "% Aged 16-34 Years") %>% # rename columns to make reader-friendly
  fmt_number(columns = c(levonorgestrel_rate, ulipristal_acetate_rate, total_ECP_rate, prop_young_ppl_hb), decimals = 0) %>% # no decimal points as false accuracy detracts from the message in the data
  cols_align(align = "center",
             columns = c(levonorgestrel_rate,ulipristal_acetate_rate,total_ECP_rate, prop_young_ppl_hb)) %>%  # centre column names
  grand_summary_rows(columns = c(levonorgestrel_rate,ulipristal_acetate_rate, total_ECP_rate),
                     fns = list("Overall Average" = ~mean(., na.rm = TRUE)),
                     fmt = list(~ fmt_number(., decimals = 0))) %>%   # add an overall average of the prescription rate columns
  fmt_percent(columns = prop_young_ppl_hb, decimals = 0) %>%  # add percentage sign
  tab_header(title = md("**Average Annual Rate of Emergency Contraception Prescriptions by Health Board in Scotland.**"),
             subtitle = md("Rate per 100,000 women, derived from the mean prescription rates across the years 2019 to 2022. Health Boards are ranked in descending order.")) %>% # add a title and subtitle; md() allows text formatting from mark down 
  tab_spanner(label = md("*Prescription rate per 100,000 women*"),
    columns = c(levonorgestrel_rate,ulipristal_acetate_rate, total_ECP_rate)) %>%   # add a title to prescription rate columns.
  tab_source_note(md("*Data from Public Health Scotland. Available from: (https://www.opendata.nhs.scot/dataset/prescriptions-in-the-community)*")) %>% 
  tab_stubhead(md("**2019-2022**")) %>% 
  tab_footnote(footnote = "includes Capital City, Edinburgh",
    locations = cells_body(columns = hb_name, rows = 2))%>% 
  opt_stylize(style = 6, color = "cyan")

annual_avg_ECP_table
Average Annual Rate of Emergency Contraception Prescriptions by Health Board in Scotland.
Rate per 100,000 women, derived from the mean prescription rates across the years 2019 to 2022. Health Boards are ranked in descending order.
2019-2022 Health Board
Prescription rate per 100,000 women
% Aged 16-34 Years
Levonorgestrel Ulipristal Acetate Total
NHS Greater Glasgow and Clyde 3,376 29 3,404 26%
NHS Lothian1 2,495 56 2,551 27%
NHS Ayrshire and Arran 2,027 15 2,043 19%
NHS Tayside 1,365 22 1,387 22%
NHS Forth Valley 1,268 73 1,342 22%
NHS Grampian 1,210 16 1,226 22%
NHS Fife 1,049 54 1,103 22%
NHS Lanarkshire 784 48 832 22%
NHS Shetland 779 17 796 19%
NHS Orkney 609 7 616 17%
NHS Dumfries and Galloway 515 24 539 17%
NHS Western Isles 192 197 389 16%
NHS Highland 285 52 337 17%
NHS Borders 242 76 318 17%
Overall Average — 1,157 49 1,206 —
Data from Public Health Scotland. Available from: (https://www.opendata.nhs.scot/dataset/prescriptions-in-the-community)
1 includes Capital City, Edinburgh

western isles relatively high uli prescription commpared to levo - explore if prescribing practices vary by location?

How does deprivation on the type of emergency contraceptive prescribed

How does deprivation influence type of contraception prescribed? I wanted to explore if there was any correlation between the type of contraception being prescribed and deprivation. To do this I made a ratio of levonogestrel to total emergency contraception prescriptions.

A/(A+B) Where A = Levonogestrel (prescribed within 3 days of unprotected sex) B = Ulipristal Acetate (prescribed within 5 days of unprotected sex)

This is important to identify any variation in prescribing patterns in more deprived areas. Differences may suggest patients access health services later, so have to use Ulipristal Acetate, or that GPs or Pharmacists have differences in prescribing preferences in more deprived areas.

To measure deprivation I have used the Scottish Index of Multiple Deprivation. I took the SIMD 2020v2 dataset from Public Health Scotland website [available from: https://www.opendata.nhs.scot/gl/dataset/scottish-index-of-multiple-deprivation/resource/acade396-8430-4b34-895a-b3e757fa346e ] as this dataset contains SIMD decile weighted per Health Board population.

When interpreting SIMD in deciles rank 1 is considered the most deprived, and rank 10 is least deprived.

# read in datasets:

SIMD <- read_csv("https://www.opendata.nhs.scot/gl/dataset/78d41fa9-1a62-4f7b-9edb-3e8522a93378/resource/acade396-8430-4b34-895a-b3e757fa346e/download/simd2020v2_22062020.csv") %>%
  clean_names() %>%
  select(data_zone, simd2020v2hb_decile)

# I chose to use GP Practices and List sizes from October 2022, as this was the closest dataset I could find which correlated with the final year of my prescriptions datset
gp_addresses <- read_csv("https://www.opendata.nhs.scot/dataset/f23655c3-6e23-4103-a511-a80d998adb90/resource/1a15cb34-fcf9-4d3f-ad63-1ba3e675fbe2/download/practice_contactdetails_oct2022-open-data.csv") %>%
  clean_names() %>%
  select(practice_code, gp_practice_name, data_zone)

# Create ECP_GP by using the GP_addresses dataset to map the GP practice code to a datazone. I then used the column datazone to full_join() the SIMD dataset to the prescriptions dataset.

ECP_GP <- ECP_scripts %>%
  filter(!gp_practice %in% c(99996, 99997, 99998)) %>% # remove dummy GP practice codes as they do not have a known gp practice code so cannot be mapped to a SIMD.
  left_join(gp_addresses, by = c("gp_practice" = "practice_code")) %>%
  #left_join(data_zones, by = "data_zone") %>%
  left_join(SIMD, by = "data_zone") %>%
  drop_na(simd2020v2hb_decile) %>% # need SIMD value to make barchart
  group_by(gp_practice) %>% 
  mutate(total_quantity_per_gp = sum(paid_quantity)) %>% 
  clean_names()

# calculate the number of GPs per health board 
toal_no_GP_per_hb <- ECP_GP %>% 
  filter(!gp_practice %in% c(99996, 99997, 99998)) %>% # remove dummy GP practice codes as they do not have a known gp practice code so cannot be mapped to a SIMD.
  group_by(hb_name) %>%
  summarise(unique_gp_count_per_hb = n_distinct(gp_practice))

# calculate average population per GP in a health board 
pop_per_gp_hb <- population_data %>% 
  full_join(toal_no_GP_per_hb) %>% 
  mutate(avg_pop_per_GP = hb_population /unique_gp_count_per_hb)

# join pop_per_gp_hb to ECP_GP 
ECP_pop_per_gp_hb <- ECP_GP %>% 
  left_join(pop_per_gp_hb)

# make bar chart
ECP_SIMD_barchart <- ECP_pop_per_gp_hb %>%
  group_by(simd2020v2hb_decile, drug) %>%
  summarise(
    prescriptions_hb_gp = (total_quantity_per_gp *10000 / avg_pop_per_GP), # summarise the prescriptions per 100,000
    .groups = "drop"  # Ungroup data after summarisation
  ) %>%
  ggplot(aes(x = prescriptions_hb_gp, y = factor(simd2020v2hb_decile, levels = 1:10), fill = drug)) +
  geom_col() +
  scale_fill_brewer(palette = "Set2", name = "Drug Type") +  # add colour palette
  labs(
    title = "Barchart to show how the prescription rate of \n Emergency Contraceptive Pill varies by Scottish Index of Multiple Deprivation",
    subtitle = "This chart shows the average prescription rate of ECP per SIMD, \n accounting for differences in number of GPs in each SIMD.",
    x = "Prescriptions per 10,000 women",
    y = "SIMD Decile \n (1 = Most Deprived, 10 = Least Deprived)",
    fill = "Drug") +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
    plot.subtitle = element_text(size = 12, hjust = 0.5),
    axis.title.x = element_text(size = 12),
    axis.title.y = element_text(size = 12),
    axis.text.x = element_text(size = 10, angle = 45, hjust = 1),
    axis.text.y = element_text(size = 10),
    legend.position = "right",
    legend.title = element_text(size = 12, face = "bold"),
    legend.text = element_text(size = 10))

ECP_SIMD_barchart <- ggplotly(ECP_SIMD_barchart)
ECP_SIMD_barchart

Prescribing choices vary per regions

# load the NHS Health board Shapefile downloaded from learn page
NHS_healthboards <- st_read(here("data", "NHS_healthboards_2019.shp")) %>% 
  mutate(HBName = paste("NHS", HBName)) %>% # format to match ECP_scripts dataset
  clean_names()
## Reading layer `NHS_healthboards_2019' from data source 
##   `C:\Data_science\B273025\data\NHS_healthboards_2019.shp' using driver `ESRI Shapefile'
## Simple feature collection with 14 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 7564.996 ymin: 530635.8 xmax: 468754.8 ymax: 1218625
## Projected CRS: OSGB36 / British National Grid
# calculate the ratio of Lev to Uli prescribed 
variation_ECP_prescribed <- ECP_scripts %>% 
  group_by(hb_name,drug) %>% 
  # calculate the total of Lev and Uli prescribed per health board
  summarise(total_each_drug_type = sum(paid_quantity, na.rm = TRUE)) %>%
  drop_na(drug) %>% 
  #pivot_wider to move drug names to columns 
  pivot_wider(names_from = drug, values_from = total_each_drug_type) %>%
  clean_names() %>% # consistency 
  mutate(levo_to_uli_ratio = levonorgestrel / (levonorgestrel + ulipristal_acetate)) # calculate ratio 

# Join spatial data with variation_ECP_prescribed
variation_ECP_prescribed <- NHS_healthboards %>%
  left_join(variation_ECP_prescribed)

#Create map in ggplot
map_variation_ECP_prescribed <- variation_ECP_prescribed %>%
  ggplot(aes(fill = levo_to_uli_ratio)) +
  geom_sf(size = 0.1, colour = "grey50", alpha =0.9) +
  scale_fill_distiller(palette = "Blues", direction = 1) +
  labs(title = "Geographical variation in Emergency Contraceptive Pill \n prescribing in Scotland.", 
       subtitle = "Heatmap showing Levonorgestrel prescriptions as a proportion of total Emergency \n Contraceptive Pill (ECP) prescriptions by Health Board region", 
       fill = "Levonorgestrel to ECP ratio", caption = "Data Source: Public Health Scotland Prescriptions in the Community, 2019-2022") +
  coord_sf() +
  theme_void() +
  theme(
    plot.title = element_text(face = "bold", size = 22, hjust=0.5), 
    plot.subtitle = element_text(size = 16, hjust=0.5), 
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 9, hjust=0.5),
    legend.direction = "vertical",
    legend.box = "horizontal") +
  annotation_scale(location = "tl") +
  annotation_north_arrow(
    location = "tl",    
    pad_y = unit(0.5, "in"),    
    style = north_arrow_nautical(fill = c("grey40", "white"),line_col = "grey20"))

map_variation_ECP_prescribed

# calculate the ratio of Lev to Uli prescribed 
variation_ECP_prescribed_v2 <- ECP_scripts %>% 
  group_by(gp_practice,drug) %>% 
  # calculate the total of Lev and Uli prescribed per health board
  summarise(total_each_drug_type = sum(paid_quantity, na.rm = TRUE)) %>%
  drop_na(drug) %>% 
  #pivot_wider to move drug names to columns 
  pivot_wider(names_from = drug, values_from = total_each_drug_type) %>%
  clean_names() %>% # consistency 
  mutate(levo_to_uli_ratio = levonorgestrel / (levonorgestrel + ulipristal_acetate)) %>% # calculate ratio %>% 
  drop_na(levo_to_uli_ratio) %>% 
  full_join(ECP_GP)

# make bar chart
ECP_SIMD_barchart_variations <- variation_ECP_prescribed_v2 %>%
  #group_by(simd2020v2hb_decile, drug) %>%
  ggplot(aes(x = factor(simd2020v2hb_decile, levels = 1:10), y = levo_to_uli_ratio, fill = drug)) +
  geom_col() +
  scale_fill_brewer(palette = "Set2", name = "Drug Type") +  # add colour palette
  labs(
    title = "Variation in prescribing practise by SIMD",
    subtitle = "",
    x = "SIMD Decile \n (1 = Most Deprived, 10 = Least Deprived)",
    y = "prescriptions",
    fill = "Drug") +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
    plot.subtitle = element_text(size = 12, hjust = 0.5),
    axis.title.x = element_text(size = 12),
    axis.title.y = element_text(size = 12),
    axis.text.x = element_text(size = 10, angle = 45, hjust = 1),
    axis.text.y = element_text(size = 10),
    legend.position = "right",
    legend.title = element_text(size = 12, face = "bold"),
    legend.text = element_text(size = 10))

ECP_SIMD_barchart_variations

Conclusion

Recommendations from analysis

Limitations of the dataset and suggestions for future analysis

References

I used https://gsverhoeven.github.io/post/zotero-rmarkdown-csl/ to set up citations. Chosen BMJ style as common.

LS0tDQp0aXRsZTogIkFzc2Vzc21lbnQiDQphdXRob3I6ICJCMjczMDI1Ig0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0KYmlibGlvZ3JhcGh5OiAiLi4vem90ZXJvX2NpdGF0aW9ucy5qc29uIg0KbGluay1jaXRhdGlvbnM6IHRydWUNCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0b2M6IHRydWUNCiAgICB0aGVtZTogZmxhdGx5DQoNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlPUZBTFNFKQ0KYGBgDQoNCiMgbWFrZSB0aGlzIGEgcXVlc3Rpb24hIEhvdyBkbyBFbWVyZ2VuY3kgQ29udHJhY2VwdGl2ZSBQaWxsIFByZXNjcmliaW5nIFBhdHRlcm5zIHZlcnkgaW4gU2NvdGxhbmQ/DQoNCk1hcmsgc2NoZW1lOg0KSnVzdGlmaWVkIOKAkyB1bmRlcnN0YW5kaW5nIG9mIHRoZSBkYXRhIGFuZCB0aGVpciBjb250ZXh0ICANCkludHJvZHVjdGlvbiAgDQpLZXkgcmVzdWx0cyAgIA0KQ29uY2x1c2lvbiANClJlZmVyZW5jZXMgKGZvciByZWFzb24gY2hvc2VuIHJlc2VhcmNoIHF1ZXN0aW9uKSAgDQpOYXJyYXRpdmUgc2hvd3MgY3JpdGljYWwgdGhpbmtpbmcgIA0KTXVsdGlwbGUgZGF0YSBzb3VyY2VzICAgDQpSZWNvbW1lbmRhdGlvbnMgYW5kIGNvbmNsdXNpb25zIGFyZSBncm91bmRlZCBpbiB0aGUgZGF0YSAgDQpMaW1pdGF0aW9ucyBvZiB0aGUgZGF0YSBzZXQgZGlzY3Vzc2VkLiBOZXh0IHN0ZXBzIHN1Z2dlc3RlZCBpbiB0ZXJtcyBvZiBkYXRhIHRoYXQgd291bGQgYWxsb3cgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuICAgDQoNCiMjIEludHJvZHVjdGlvbiANCg0KVGhlcmUgYXJlIHR3byB0eXBlcyBvZiBlbWVyZ2VuY3kgY29udHJhY2VwdGl2ZSBwaWxsIHByZXNjcmliZWQgYnkgcGhhcm1hY2llcy4NCg0KPiogKipMZXZvbm9nZXN0cmVsKiogKGJyYW5kIG5hbWU6ICpMZXZvbmVsbGUqKSB0YWtlbiB3aXRoaW4gdGhyZWUgZGF5cyBvZiB1bnByb3RlY3RlZCBzZXgNCj4qICoqVWxpcHJpc3RhbCBBY2V0YXRlKiogKGJyYW5kIG5hbWU6ICplbGxhT25lKikgdGFrZW4gd2l0aGluIGZpdmUgZGF5cyBvZiB1bnByb3RlY3RlZCBzZXggIA0KDQoNClRoaXMgcmVwb3J0IGV4cGxvcmVzIA0KDQoxKSBQcmVzY3JpYmluZyBwYXR0ZXJucyBvZiBlbWVyZ2VuY3kgY29udHJhY2VwdGl2ZSBwaWxsIChFQ1ApIGJldHdlZW4gMjAxOSB0byAyMDIzLiANCg0KMikgSG93IEVDUCBhbmQgYW50aWJpb3RpY3MgZm9yIFNUSSBwcmVzY3JpcHRpb25zIGRpZmZlciBpbiBnZW9ncmFwaHkgY29tcGFyaW5nIHVuaXZlcnNpdHkgdG93biB0byBhIG5vbi11bml2ZXJzaXR5IHRvd24gDQoNCjMpIENvbXBhcmUgcGF0dGVybnMgaW4gRUNQIGFuZCBTVEkgYW50aWJpb3RpY3MgcHJlc2NyaWJpbmcgZHVyaW5nIENvdmlkLTE5IGxvY2tkb3ducyAtIGRpZCB0aGUgbmVlZCBmb3IgRUNQIG9yIGluY2lkZW5jZSBvZiBTVEkgYW50aWJpb3RpY3MgcHJlc2NyaXB0aW9uIGdvIGRvd24gZHVyaW5nIGxvY2tkb3ducz8NCg0KNCkgSG93IGRvZXMgU0lNRCByZWxhdGUgdG8gcHJlc2NyaXB0aW9uIG9mIEVDUCAvIGFudGliaW90aWNzIGZvciBTVElzIA0KDQpgYGB7cn0NCiMgbG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoamFuaXRvcikgDQpsaWJyYXJ5KGd0KSANCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShzZikNCmxpYnJhcnkoZ2dzcGF0aWFsKQ0KbGlicmFyeShwbG90bHkpDQpgYGANCg0KSSBoYXZlIGNob3NlbiB0byBsb29rIGF0IGFsbCBwcmVzY3JpcHRpb25zIGZyb20gMjAxOSBhbmQgMjAyMi4gVG8gZG8gdGhpcyBJIGRvd25sb2FkZWQgdGhlIHByZXNjcmlwdGlvbnMgZGF0YSBmb3IgZWFjaCBtb250aCBmcm9tOiBodHRwczovL3d3dy5vcGVuZGF0YS5uaHMuc2NvdC9kYXRhc2V0L3ByZXNjcmlwdGlvbnMtaW4tdGhlLWNvbW11bml0eSAgDQoNCkkgd2FudGVkIHRvIGV4cGxvcmUgaG93IG1hbnkgRUNQIGFuZCBhbnRpYmlvdGljcyBmb3IgU1RJcyB3ZXJlIHByZXNjaWJlZCBkdXJpbmcgYWNyb3NzIDIwMjMuDQoNCg0KPjQgcGxvdHMgYW5kIC8gb3IgdGFibGVzIA0KTm8gdXNlIG9mIHNldHRpbmdzIG90aGVyIHRoYW4gZGVmYXVsdCANCkxhYmVsbGVkLCB0aXRsZWQgcGxvdHMgDQpMYWJlbGxlZCB0aXRsZWQgdGFibGVzIA0KQXBwcm9wcmlhdGUgYW5kIHRob3VnaHRmdWwgZGF0YSB2aXN1YWxpc2F0aW9uIHdpdGggc29tZSB1c2Ugb2Ygbm9uLWRlZmF1bHQgc2V0dGluZ3MgKGd0KQ0KRmFjZXRpbmcsIG11bHRpbGF5ZXJlZCBwbG90cywgaW50ZXJhY3RpdmUgdmlzdWFsaXNhdGlvbiANCg0KUmVhZCBpbiBkYXRhOg0KYGBge3J9DQojIFJlYWQgaW4gdGhlIEhlYWx0aCBCb2FyZCBuYW1lcyAoSEJfbmFtZXMpLiBTZWUgY29kZSBmb3IgbGluaw0KSEJfbmFtZXMgPC0gcmVhZF9jc3YoImh0dHBzOi8vd3d3Lm9wZW5kYXRhLm5ocy5zY290L2RhdGFzZXQvOWY5NDJmZGItZTU5ZS00NGY1LWI1MzQtZDZlMTcyMjljYzdiL3Jlc291cmNlLzY1MmZmNzI2LWU2NzYtNGEyMC1hYmRhLTQzNWI5OGRkN2JkYy9kb3dubG9hZC9oYjE0X2hiMTkuY3N2IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICMgZW5zdXJlcyBjb2x1bW4gbmFtZXMgYXJlIHVuaXF1ZSwgbG93ZXIgY2FzZSBhbmQgcmVwbGFjZXMgc3BhY2VzIGFuZCBzcGVjaWFsIGNoYXJhY3RlcnMgd2l0aCB1bmRlcnNjb3Jlcy4gSSB3aWxsIHVzZSB0aGlzIGZ1bmN0aW9uIGZvciBhbGwgcmVhZCBpbnMgdG8gZW5zdXJlIG15IGRhdGEgaXMgY29uc2lzdGVudCBhbmQgZWFzeSB0byBtYW5pcHVsYXRlLg0KDQoNCiMgUmVhZCBpbiBwb3B1bGF0aW9uIGRhdGEgcGVyIEhlYWx0aCBCb2FyZCBmcm9tIHRoZSAyMDIyIGNlbnN1cyBkYXRhLiBBdmFpbGFibGUgZnJvbTogaHR0cHM6Ly9zdGF0aXN0aWNzLnVrZGF0YXNlcnZpY2UuYWMudWsvZGF0YXNldC9zY290bGFuZC1zLWNlbnN1cy0yMDIyLXV2MTAyYS1hZ2UtYnktc2V4L3Jlc291cmNlL2IyZDI5NWMyLWFmNTMtNGIzZC1hMDc1LTc4MTVjYWRkOTA2MCANCmFsbF9wb3B1bGF0aW9uX2RhdGEgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsICJVVjEwM19hZ2VfaGVhbHRoX2JvYXJkX2NlbnN1cy5jc3YiKSwgc2tpcCA9IDEwKSAlPiUgIyBsb2NhdGVzIHRoZSBjc3YgYW5kIGV4Y2x1ZGVzIHRoZSBmaXJzdCAxMCBsaW5lcyBpbiB0aGUgY3N2IGFzIHRoZXkgYXJlIHJlZHVuZGFudA0KICByZW5hbWUoU3BhcmUgPSAiLi4uNiIsICMgcmVtb3ZlIHVudXNlZCBjb2x1bW5zDQogICAgICAgICBoYl9uYW1lID0gIkhlYWx0aCBCb2FyZCBBcmVhIDIwMTkiLA0KICAgICAgICAgaGJfcG9wdWxhdGlvbiA9IENvdW50KSAlPiUgIyByZW5hbWUoKSBmb3JtYXRzIHRoZSBkYXRhIHRvIG1hdGNoIHRoZSBwcmVzY3JpcHRpb25zIGRhdGFmcmFtZQ0KICBmaWx0ZXIoU2V4ID09ICJGZW1hbGUiKSAlPiUgIyBmaWx0ZXIgZmVtYWxlIHBvcHVsYXRpb24sIGFzIG1lbiBkbyBub3QgdGFrZSBFQ1ANCiAgc2VsZWN0KGhiX25hbWUsIEFnZSwgaGJfcG9wdWxhdGlvbikgJT4lICMgc2VsZWN0IGNvbHVtbnMgb2YgaW50ZXJlc3QNCiAgbXV0YXRlKGhiX25hbWUgPSBwYXN0ZSgiTkhTIiwgaGJfbmFtZSkpICU+JSAgIyBjaGFuZ2UgaGJfbmFtZSBjb2x1bW4gZm9ybWF0IHRvIG1hdGNoIHRoZSBIZWFsdGggQm9hcmQgZGF0YWZyYW1lIGZvcm1hdA0KICBjbGVhbl9uYW1lcygpDQoNCiMgY3JlYXRlIGRhdGFzZXQgd2l0aCB0b3RhbCBwb3B1bGF0aW9uIGZvciBlYWNoIGhlYWx0aCBib2FyZA0KcG9wdWxhdGlvbl9kYXRhIDwtIGFsbF9wb3B1bGF0aW9uX2RhdGEgJT4lIA0KICBmaWx0ZXIoYWdlID09ICJBbGwgcGVvcGxlIikgJT4lIA0KICBzZWxlY3QoaGJfbmFtZSwgaGJfcG9wdWxhdGlvbikNCg0KIyBzZWxlY3QgdGhlIHBvcHVsYXRpb24gYWdlZCAxNiB0byAzNCB5ZWFycyBhcyB0aGlzIGlzIHRoZSBwb3B1bGF0aW9uIHRoZSBwb3B1bGF0aW9uIG1vc3QgbGlrZWx5IGVuZ2FnaW5nIHdpdGggcmlzayB0YWtpbmcgYmVoYXZpb3JzIHN1Y2ggYXMgdW5wcm90ZWN0ZWQgc2V4LiBJIGNob3NlIDE2IGFzIHRoaXMgaXMgdGhlIGFnZSBvZiBjb25zZW50IGluIFNjb3RsYW5kLCBhbmQgMzQgYXMgbXkgY3V0IG9mZiBmb3IgeW91bmcgYWR1bHRzLiANCmFnZV9wb3B1bGF0aW9uX2RhdGEgPC0gYWxsX3BvcHVsYXRpb25fZGF0YSAlPiUgDQogIGZpbHRlcihhZ2UlaW4lIGMoMTY6MzQpKSAlPiUgIyBmaWx0ZXIgYWdlcyBvZiBpbnRlcmVzdA0KICBtdXRhdGUoYWdlID0gYXMubnVtZXJpYyhhZ2UpKSAlPiUgIyBtYWtlIG51bWVyaWNhbCBzbyB0aGV5IGNhbiBiZSBwbGFjZWQgaW4gdG8gYnVja2V0cw0KICBtdXRhdGUoYWdlX2dyb3VwID0gY2FzZV93aGVuKGJldHdlZW4oYWdlLCAxNiwzNCl+JzE2LTM0JykpICU+JSAjIG1ha2UgYnVja2V0IDE2LTM0IHllYXJzDQogIGdyb3VwX2J5KGhiX25hbWUsIGFnZV9ncm91cCkgJT4lIA0KICBzdW1tYXJpc2UocG9wX2hiXzE2XzM0ID0gc3VtKGhiX3BvcHVsYXRpb24pKSAjIHN1bSB0b3RhbCBwb3B1bGF0aW9uIGFnZWQgMTYgdG8gMzQgcGVyIGhlYWx0aCBib2FyZCByZWdpb24uIA0KDQpgYGANCg0KDQpEZWZpbmUgYSBmdW5jdGlvbiB0byByZWFkIGluIHRoZSBwcmVzY3JpcHRpb24gZGF0YSBmb3IgYSBkZWZpbmVkIHllYXI6DQpgYGB7cn0NCiMgI0ZvciBlZmZpY2llbmN5IEkgY3JlYXRlZCBhIGZ1bmN0aW9uIHRvIHJlYWQgaW4gbXkgcHJlc2NyaXB0aW9ucyBkYXRhc2V0cy4NCiMgI0kgZG93bmxvYWRlZCAxMiBtb250aHMgb2YgcHJlc2NyaXB0aW9uIGRhdGEgZm9yIGVhY2ggeWVhciBmcm9tIDIwMTkgdG8gMjAyMi4gSSBwbGFjZWQgdGhlIDEyIG1vbnRocyBvZiBkYXRhIGludG8gdGhlaXIgcmVsZXZhbnQgZm9sZGVyIG5hbWVkIGFsbF9tb250aHNfeWVhciwgd2hlcmUgeWVhciB3YXMgc3BlY2lmaWMgdG8gdGhlIGRhdGEgaXQgY29udGFpbmVkLg0KIyByZWFkX2FsbF9wcmVzY3JpcHRpb25zIDwtIGZ1bmN0aW9uKHllYXIpew0KIyAgIGFsbF9maWxlcyA8LSBsaXN0LmZpbGVzKGhlcmUoImRhdGEiLCBwYXN0ZTAoImFsbF9tb250aHNfIiwgeWVhcikpLCBwYXR0ZXJuID0gImNzdiIpICNsaXN0LmZpbGVzKCkgcmV0cmlldmVzIGZpbGVzIGZyb20gdGhlIHJlbGV2YW50IGRpcmVjdG9yeSwgYW5kIHRoZSBwYXN0ZTAoKSBkeW5hbWljYWxseSBjb25zdHJ1Y3RzIHRoZSBmb2xkZXIgbmFtZSBiYXNlZCBvbiB0aGUgeWVhciB2YXJpYWJsZSBwbGFjZWQgaW50byB0aGUgZnVuY3Rpb24uDQojICAgYWxsX3ByZXNjcmlwdGlvbnMgPC0gYWxsX2ZpbGVzICU+JQ0KIyAgICAgbWFwX2Rmcih+cmVhZF9jc3YoaGVyZSgiZGF0YSIsIHBhc3RlMCgiYWxsX21vbnRoc18iLCB5ZWFyKSwuKSkpICU+JSAjbWFwX2RmcigpIHJvdy1iaW5kcyB0aGUgZGF0YXNldHMgYmVpbmcgcmVkIGluDQojICAgICBjbGVhbl9uYW1lcygpICU+JQ0KIyAgICAgZHJvcF9uYShibmZfaXRlbV9kZXNjcmlwdGlvbikgIyBkcm9wIHRoZSByb3dzIHdpdGggbWlzc2luZyBibmZfaXRlbSB2YWx1ZXMNCiMgICByZXR1cm4oYWxsX3ByZXNjcmlwdGlvbnMpDQojIH0NCmBgYA0KDQpSZWFkIGluIGRhdGFzZXRzIHVzaW5nIHJlYWRfYWxsX3ByZXNjcmlwdGlvbnMoKSBmdW5jdGlvbiBhbmQgc3RhcnQgdGlkeWluZzoNCmBgYHtyfQ0KIyBhbGxfcHJlc2NyaXB0aW9uc18yMDE5IDwtIHJlYWRfYWxsX3ByZXNjcmlwdGlvbnMoMjAxOSkNCiMgYWxsX3ByZXNjcmlwdGlvbnNfMjAyMCA8LSByZWFkX2FsbF9wcmVzY3JpcHRpb25zKDIwMjApDQojIGFsbF9wcmVzY3JpcHRpb25zXzIwMjEgPC0gcmVhZF9hbGxfcHJlc2NyaXB0aW9ucygyMDIxKQ0KIyBhbGxfcHJlc2NyaXB0aW9uc18yMDIyIDwtIHJlYWRfYWxsX3ByZXNjcmlwdGlvbnMoMjAyMikNCiMgDQojICMgMjAxOSBkYXRhc2V0IGhhcyBoYnQyMDE0IGFzIGEgY29sdW1uIG5hbWUgaW5zdGVhZCBvZiBoYnQuIFJlbmFtZSB0byBtYWtlIGNvbHVtbiBuYW1lIGNvbnNpc3RlbnQNCiMgYWxsX3ByZXNjcmlwdGlvbnNfMjAxOSA8LSBhbGxfcHJlc2NyaXB0aW9uc18yMDE5ICU+JQ0KIyAgIHJlbmFtZShoYnQgPSAiaGJ0MjAxNCIpDQojIA0KIyAjIGNvbWJpbmUgNCB5ZWFycyBvZiBkYXRhIGludG8gb25lIGRhdGFzZXQgdG8gbWFrZSBpdCBlYXNpZXIgdG8gd3JhbmdsZQ0KIyBjb21iaW5lZF9wcmVzY3JpcHRpb25zIDwtIGJpbmRfcm93cygNCiMgICBhbGxfcHJlc2NyaXB0aW9uc18yMDE5LA0KIyAgIGFsbF9wcmVzY3JpcHRpb25zXzIwMjAsDQojICAgYWxsX3ByZXNjcmlwdGlvbnNfMjAyMSwNCiMgICBhbGxfcHJlc2NyaXB0aW9uc18yMDIyICklPiUgIyBJIG11dGF0ZSBlYXJseSBhbmQgc2VsZWN0IHRoZSBwcmVzY3JpcHRpb25zIG9mIGludGVyZXN0IHRvIHByZXZlbnQgYSB2ZXJ5IGxhcmdlIGRhdGFzZXQgZnJvbSBiZWluZyBzdG9yZWQgaW4gbXkgZW52aXJvbm1lbnQgKHByZXZlbnRzIFIgc2xvd2luZyBkb3duIGFuZCBjcmFzaGluZykNCiMgICBtdXRhdGUoDQojICAgICBkYXRlID0gcGFyc2VfZGF0ZV90aW1lKHBhaWRfZGF0ZV9tb250aCwgInltIiksICMgdXNlIGx1YnJpZGF0ZSB0byBmb3JtYXQgZGF0ZQ0KIyAgICAgZHJ1Z19zaW1wbGUgPSBjYXNlX3doZW4oDQojICAgICAgIHN0cl9kZXRlY3QoYm5mX2l0ZW1fZGVzY3JpcHRpb24sICJMRVZPTk8iKSB+ICJMZXZvbm9yZ2VzdHJlbCIsDQojICAgICAgIHN0cl9kZXRlY3QoYm5mX2l0ZW1fZGVzY3JpcHRpb24sICJVTElQUiIpIH4gIlVsaXByaXN0YWwgQWNldGF0ZSIsDQojICAgICAgIFRSVUUgfiAiT3RoZXIiKSkgJT4lICMgdXNlZCBjYXNlX3doZW4oKSB0byBncm91cCBkaWZmZXJlbnQgZG9zYWdlcyBvZiB0aGUgc2FtZSBkcnVnDQojICAgZmlsdGVyKGRydWdfc2ltcGxlICE9ICJPdGhlciIsIWlzLm5hKGRhdGUpKSAlPiUgI3JlbW92ZSBwcmVzY3JpcHRpb25zIG9mIG5vIGludGVyZXN0IGFuZCBhbnkgbWlzc2luZyBkYXRlIHZhbHVlcw0KIyAgIGZpbHRlcihoYnQgIT0gIlNCMDgwNiIpICU+JSAjIGZpbHRlciBvdXQgU0IwODA2IGFzIGl0IGlzIG5vdCBhIGhlYWx0aCBib2FyZCAoU2NvdHRpc2ggQW1idWxhbmNlIFNlcnZpY2UpDQojICAgZmlsdGVyKCFpcy5uYShoYnQpKQ0KDQojICMgc2F2ZSBjb21iaW5lZF9wcmVzY3JpcHRpb25zIGRhdGFzZXQgdG8gY3N2DQojICMgd3JpdGVfY3N2KGNvbWJpbmVkX3ByZXNjcmlwdGlvbnMsImRhdGEvY29tYmluZWRfcHJlc2NyaXB0aW9ucy5jc3YiKQ0KDQojIGZpbHRlciBkcnVncyBvZiBpbnRlcmVzZXQgYmVmb3JlIGNvbXBsZXRpbmcgcmVhZCBpbiB0byBwcmV2ZW50IGxvYWRpbmcgbGFyZ2UgZGF0YXNldHMgaW50byB0aGUgZW52aXJvbm1lbnQgKHByZXZlbnRzIFIgZnJvbSBydW5uaW5nIHNsb3cgYW5kIGNyYXNoaW5nKQ0KY29tYmluZWRfcHJlc2NyaXB0aW9ucyA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwiY29tYmluZWRfcHJlc2NyaXB0aW9ucy5jc3YiKSkgJT4lDQogIG11dGF0ZSgNCiAgICBkYXRlID0gcGFyc2VfZGF0ZV90aW1lKHBhaWRfZGF0ZV9tb250aCwgInltIiksICMgdXNlIGx1YnJpZGF0ZSB0byBmb3JtYXQgZGF0ZQ0KICAgIGRydWdfc2ltcGxlID0gY2FzZV93aGVuKA0KICAgICAgc3RyX2RldGVjdChibmZfaXRlbV9kZXNjcmlwdGlvbiwgIkxFVk9OTyIpIH4gIkxldm9ub3JnZXN0cmVsIiwNCiAgICAgIHN0cl9kZXRlY3QoYm5mX2l0ZW1fZGVzY3JpcHRpb24sICJVTElQUiIpIH4gIlVsaXByaXN0YWwgQWNldGF0ZSIsDQogICAgICBUUlVFIH4gIk90aGVyIikpICU+JSAjIHVzZWQgY2FzZV93aGVuKCkgdG8gZ3JvdXAgZGlmZmVyZW50IGRvc2FnZXMgb2YgdGhlIHNhbWUgZHJ1Zw0KICBmaWx0ZXIoZHJ1Z19zaW1wbGUgIT0gIk90aGVyIiwhaXMubmEoZGF0ZSkpJT4lICAjIHJlbW92ZSBvdGhlciBwcmVzY3JpcHRpb25zIGZyb20gdGhlIGRhdGFzZXQgYW5kIGFueSBtaXNzaW5nIGRhdGUgdmFsdWVzDQogIGZpbHRlcihoYnQgIT0gIlNCMDgwNiIpICU+JSAjIGZpbHRlciBvdXQgU0IwODA2IGFzIGl0IGlzIG5vdCBhIGhlYWx0aCBib2FyZCAoU2NvdHRpc2ggQW1idWxhbmNlIFNlcnZpY2UpDQogIGZpbHRlcighaXMubmEoaGJ0KSkNCg0KYGBgDQoNCkpvaW4gYW5kIHdyYW5nbGUgZGF0YToNCmBgYHtyfQ0KIyBqb2luIHRoZSBQcmVzY3JpcHRpb25zIGRhdGFzZXQgdG8gdGhlIEhlYWx0aCBCb2FyZCBuYW1lcyBkYXRhc2V0IGFuZCBoZWFsdGggYm9hcmQgcG9wdWxhdGlvbiBkYXRhDQpFQ1Bfc2NyaXB0cyA8LSBjb21iaW5lZF9wcmVzY3JpcHRpb25zICU+JSANCiAgZnVsbF9qb2luKEhCX25hbWVzLCBieSA9IGMoImhidCIgPSAiaGIiKSkgJT4lICMgSm9pbiB3aXRoIEhlYWx0aCBCb2FyZCBuYW1lcw0KICBmdWxsX2pvaW4ocG9wdWxhdGlvbl9kYXRhLCBieSA9ICJoYl9uYW1lIikgJT4lICMgSm9pbiB3aXRoIHBvcHVsYXRpb24gZGF0YQ0KICBzZWxlY3QoZ3BfcHJhY3RpY2UsIGRhdGUsIGRydWcgPSBkcnVnX3NpbXBsZSwgaGJfbmFtZSwgcGFpZF9xdWFudGl0eSxoYl9wb3B1bGF0aW9uKSAlPiUgICMgc2VsZWN0IGNvbHVtbnMgb2YgaW50ZXJlc3QNCiAgbXV0YXRlKG1vbnRoID0gZmFjdG9yKG1vbnRoKGRhdGUpLCBsZXZlbHMgPSAxOjEyLCBsYWJlbHMgPSBtb250aC5hYmIpLCAuYWZ0ZXIgPSBkYXRlKSAlPiUgICAjIGV4dHJhY3QgbW9udGggYXMgYSBmYWN0b3Igd2l0aCBsYWJlbHMgdG8gaGVscCB3aGVuIHBsb3R0aW5nDQogIG11dGF0ZSh5ZWFyID0gZmFjdG9yKHllYXIoZGF0ZSkpLCAuYWZ0ZXIgPSBtb250aCkgDQoNCmBgYA0KDQojIyBLZXkgUmVzdWx0cyANCg0KIyMjIFdoYXQgYXJlIHRoZSBzZWFzb25hbCB0cmVuZHMgaW4gcHJlc2NyaWJpbmcgb2YgRW1lcmdlbmN5IENvbnRyYWNwZXRpb24gUGlsbHMgaW4gdGhlIHllYXJzIDIwMTkgdG8gMjAyMj8gDQoNClRoaXMgZ3JhcGggZXhwbG9yZXMgc2Vhc29uYWwgdHJlbmRzIGluIHByZXNjcmliaW5nIG9mIHRoZSB0d28gbW9zdCBjb21tb25seSBwcmVzY3JpYmVkIGVtZXJnZW5jeSBjb250cmFjZXB0aXZlIHBpbGxzLCBMZXZvbm9nZXN0cmVsIGFuZCBVbGlwcmlzdGFsIEFjZXRhdGUsIGJldHdlZW4gMjAxOSB0byAyMDIyIGJ5IEhlYWx0aCBCb2FyZC4gSSBwbG90dGVkIHRoaXMgdG8gc2VlIGlmIGV2ZW50cyBzdWNoIGFzIFZhbGVudGluZXMgZGF5LCBVbml2ZXJzaXR5IHRlcm0gc3RhcnQgZGF0ZXMsIG9yIG5hdGlvbmFsIGhvbGlkYXlzIGVmZmVjdCBlbWVyZ2VuY3kgY29udHJhY2VwdGl2ZSBwcmVzY3JpYmluZyByYXRlcy4gSSBpbmNsdWRlZCA0IHllYXJzIG9mIGNvbnNlY3V0aXZlIGRhdGEgdG8gc2VlIGlmIGEgb25lLXRpbWUgZXZlbnQsIHN1Y2ggYXMgdGhlIENvbW1vbiBXZWFsdGggR2FtZXMgY2F1c2VkIGFueSBzcGlrZXMgaW4gZW1lcmdlbmN5IGNvbnRyYWNlcHRpb24gcHJlc2NyaWJpbmcuIEFkZGl0aW9uYWxseSBieSBwbG90dGluZyB0aGUgNCBjb25zZWN1dGl2ZSB5ZWFycyB3ZSBjYW4gc2VlIGlmIENvdmlkLTE5IGxvY2tkb3ducyBpbiB0aGUgeWVhcnMgMjAyMCBhbmQgMjAyMSBhZmZlY3RlZCBlbWVyZ2VuY3kgY29udHJhY2VwdGlvbiBwcmVzY3JpYmluZyByYXRlcy4NCg0KUGxvdDoNClBvcHVsYXRpb24tV2VpZ2h0ZWQgUmF0ZXM6IEVuc3VyZXMgdGhhdCBuYXRpb25hbCB0cmVuZHMgYXJlIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIHRvdGFsIHBvcHVsYXRpb24gYWNyb3NzIGFsbCBoZWFsdGggYm9hcmRzLCBhdm9pZGluZyBiaWFzIGZyb20gc21hbGxlciByZWdpb25zLg0KQWNjdXJhdGUgTmF0aW9uYWwtTGV2ZWwgSW5zaWdodHM6IEJldHRlciByZWZsZWN0cyBvdmVyYWxsIHByZXNjcmliaW5nIGJlaGF2aW91ciBhdCB0aGUgbmF0aW9uYWwgbGV2ZWwsIGFsaWduaW5nIHdpdGggeW91ciBnb2FsIHRvIGFuYWx5c2Ugc2Vhc29uYWwgYW5kIG5hdGlvbmFsIGV2ZW50cy4NCnByZXNjcmliaW5nIHJhdGVzIGFyZSB3ZWlnaHRlZCBieSB0aGUgdG90YWwgcG9wdWxhdGlvbiwgcHJvdmlkaW5nIGFuIGFjY3VyYXRlIHJlZmxlY3Rpb24gb2Ygb3ZlcmFsbCBwcmVzY3JpYmluZyBiZWhhdmlvdXIgYWNyb3NzIFNjb3RsYW5kLg0KDQpgYGB7cn0NCnRvdGFsX3BvcHVsYXRpb24gPC0gc3VtKHBvcHVsYXRpb25fZGF0YSRoYl9wb3B1bGF0aW9uLCBuYS5ybT1UUlVFKSAjIGNhbGN1bGF0ZSB0b3RhbCBwb3B1bGF0aW9uIG9mIFNjb3RsYW5kDQoNCiMgY2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgcHJlc2NyaXB0aW9ucyBvZiBlYWNoIGRydWcgcGVyIG1vbnRoDQpFQ1BfYnlfbW9udGggPC0gRUNQX3NjcmlwdHMgJT4lDQogIGdyb3VwX2J5KGRhdGUsIGRydWcsIG1vbnRoLCB5ZWFyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX3F1YW50aXR5X21vbnRoID0gc3VtKHBhaWRfcXVhbnRpdHksIG5hLnJtID0gVFJVRSkpICU+JQ0KICB1bmdyb3VwKCkgJT4lIA0KICBkcm9wX25hKGRydWcpICU+JSANCiAgY2xlYW5fbmFtZXMoKQ0KDQojIGNhbGN1bGF0ZSBwcmVzY3JpcHRpb24gcmF0ZSBwZXIgMTAwLDAwMCBwZW9wbGUgZm9yIGVhY2ggZHJ1ZyBhbmQgbW9udGgNCkVDUF90cmVuZF9wbG90X2RhdGEgPC0gRUNQX2J5X21vbnRoICU+JQ0KICBncm91cF9ieShkcnVnLCB5ZWFyLCBtb250aCkgJT4lIA0KICBzdW1tYXJpc2UocHJlc2NyaXB0aW9uc19wZXJfMTAwMDAwID0gKHRvdGFsX3F1YW50aXR5X21vbnRoIC8gdG90YWxfcG9wdWxhdGlvbikqMTAwMDAwKQ0KDQpFQ1BfdHJlbmRfcGxvdCA8LSBFQ1BfdHJlbmRfcGxvdF9kYXRhICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBtb250aCwgeSA9IHByZXNjcmlwdGlvbnNfcGVyXzEwMDAwMCwgZ3JvdXAgPSB5ZWFyLCBsaW5ldHlwZSA9IHllYXIsIGNvbG9yID0geWVhcikpICsgIyBwbG90IGRhdGEgZm9yIGVhY2ggeWVhciBvbiBzYW1lIGdyYXBoDQogIGdlb21fbGluZShhZXMoc2l6ZSA9IGlmZWxzZSh5ZWFyID09ICIyMDIwIiwgMC45LCAwLjcpKSkgKyAjIG1ha2UgdGhlIDIwMjAgbGluZSBzbGlnaHRseSB0aGlja2VyIHRvIG1ha2UgaXQgc3RhbmQgb3V0IA0KICBmYWNldF93cmFwKH5kcnVnLCBzY2FsZXMgPSAiZnJlZV95IikgKyAjIHNlcGFyYXRlIHRoZSB0d28gdHlwZXMgb2YgRUNQDQogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKCIyMDE5IiA9ICJkb3RkYXNoIiwgIjIwMjAiID0gInNvbGlkIiwgIjIwMjEiID0gImRhc2hlZCIsICIyMDIyIiA9ICJkb3R0ZWQiKSxuYW1lID0gIlllYXIiKSArICMgbWFrZSBlYWNoIHllYXIgaWRlbnRpZmlhYmxlIGJ5IGxpbnRlIHR5cGUNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjIwMTkiID0gImdyZXk3MCIsICIyMDIwIiA9ICJyZWQiLCAiMjAyMSIgPSAiZ3JleTcwIiwgIjIwMjIiID0gImdyZXk3MCIpLG5hbWUgPSAiWWVhciIpICsgIyBtYWtlIENvdmlkLTE5IHllYXIgcmVkICgyMDIwIGhhZCB0aGUgbG9uZ2VzdCBsb2NrZG93biwgTWFyY2ggdGlsbCBNYXkpDQogIHNjYWxlX3NpemVfaWRlbnRpdHkoKSArICMgRW5zdXJlcyBnZ3Bsb3QgdXNlcyB0aGUgc2l6ZSB2YWx1ZXMgYXMgb3V0bGluZWQgaW4gZ2VvbV9saW5lKCkNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgTkEpLCBicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDUpKSsgIyBFbnN1cmUgeS1heGlzIHN0YXJ0cyBhdCAwIGFuZCBoYXMgZXZlbmx5IHNwYWNlZCBicmVha3MgDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVHJlbmRzIGluIEVtZXJnZW5jeSBDb250cmFjZXB0aW9uIFByZXNjcmliaW5nIDIwMTnigJMyMDIyIGluIFNjb3RsYW5kLiIsDQogICAgc3VidGl0bGUgPSAiRm91ciB5ZWFycyBvZiBwb3B1bGF0aW9uIGFkanVzdGVkIHByZXNjcmliaW5nIHJhdGVzIGhpZ2hsaWdodGluZyB0aGUgaW1wYWN0IG9mIENvdmlkLTE5IChyZWQpIiwNCiAgICB4ID0gIk1vbnRoIiwNCiAgICB5ID0gIlByZXNjcmlwdGlvbnMgcGVyIDEwMCwwMDAgd29tZW4iKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyLCBoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGhqdXN0ID0gMC41KSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA5KSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQoNCkVDUF90cmVuZF9wbG90DQpgYGANCg0KDQppbnZlc3RpZ2F0ZSB3aGF0IGhhcHBlbmVkIGluIDIwMTkgLSBjaGFuZ2UgaW4gcHJlc2NyaXB0aW9uIHByYWN0aXNlcyBvdmVyIHRpbWUgPyANCmRpZCB0aGV5IHVzZWQgdG8gdXNlIGl0IGZvciBzb21ldGhpbmcgZWxzZT8gDQoNClRyZW5kcyB0byBub3RlOg0KDQoqIExldm9ub3JnZXN0cmVsIGlzIG1vcmUgY29tbW9ubHkgcHJlc2NyaWJlZCB0aGFuIFVsaXByaXN0YWwgQWNldGF0ZS4gDQoqIDIwMTkgYW5kIDIwMjIgcmVwcmVzZW50IHllYXJzIHdpdGhvdXQgQ292aWQtMTkgbG9ja2Rvd24gbWVhc3VyZXMuIDIwMTkgYW5kIDIwMjIgaGF2ZSBhIHBlYWsgaW4gcHJlc2NyaXB0aW9ucyBvZiBMZXZvbm9yZ2VzdHJlbCBpbiBPY3RvYmVyIGFuZCBBdWd1c3QgcmVzcGVjdGl2ZWx5LiBUaGlzIHBlcmhhcHMgcmVmbGVjdHMgaW5jcmVhc2VkIHNleHVhbCBhY3Rpdml0eSBjb3VwbGVkIHdpdGggdGhlIHJldHVybiB0byB1bml2ZXJzaXR5IHdpdGggJ2ZyZXNoZXInIHdlZWsuIA0KKiBCZXR3ZWVuIEZlYnVhcnkgYW5kIE1heSBvZiAyMDIwIHRoZSBwcmVzY3JpcHRpb24gcmF0ZSBvZiBMZXZvbm9yZ2VzdHJlbCBkZWNyZWFzZXMuIFRoaXMgaXMgbGlrZWx5IGR1ZSB0byBkZWNyZWFzZWQgc2V4dWFsIGFjdGl2aXR5IGFuZCByaXNrIHRha2luZyBiZWhhdmlvdXJzIGR1ZSB0byB0aGUgc3RyaW5nZW50IG5hdGlvbmFsICdsb2NrZG93bicgbWVhc3VyZXMgaW50cm9kdWNlZCBiZXR3ZWVuIFggdG8gWSBpbiByZXNwb25zZSB0byB0aGUgQ292aWQtMTkgcGFuZGVtaWMuIA0KKiBBdCB0aGUgc3RhcnQgb2YgMjAyMSBwcmVzY3JpcHRpb24gcmF0ZSBvZiBMZXZvbm9yZ2VzdHJlbCBpcyB2ZXJ5IGxvdy4gTGlrZWx5IGR1ZSB0byBhZGRpdGlvbmFsIENvdmlkLTE5IGxvY2tkb3ducy4NCg0KSXQgd291bGQgYmUgaW50ZXJlc3RpbmcgdG8gZXhwbG9yZSBpZiBkaWZmZXJlbnQgSGVhbHRoIEJvYXJkcyBwcmVzY3JpYmUgZGlmZmVyZW50IGFtb3VudHMgb2YgRUNQLiANCg0KIyMjIFdoaWNoIEhlYWx0aCBCb2FyZCBpcyBwcmVzY3JpYmluZyB0aGUgbW9zdCBFQ1A/IA0KdG8gc2VlIGlmIHRoZXJlIGlzIGEgdHJlbmQgYmV0d2VlbiByYXRlIG9mIHByZXNjcmliaW5nIG9mIEVDUCBhbmQgcHJvcG9ydGlvbiBvZiB5b3VuZyBwZW9wbGUgbGl2aW5nIGluIHRoZSBIQg0KDQpgYGB7cn0NCiMgdGlkeSBkYXRhIHRvIG1ha2UgdGFibGUgd2l0aCBjb2x1bW5zIGFuZCB2YWx1ZXMgb2YgaW50ZXJlc3QgDQpFQ1BfYW51YWxfcmF0ZV9kYXRhIDwtIEVDUF9zY3JpcHRzICU+JSANCiAgZ3JvdXBfYnkoaGJfbmFtZSwgZHJ1ZykgJT4lICAjIGFnZ3JlZ2F0ZSBkYXRhIGJ5IEhlYWx0aCBCb2FyZCBhbmQgZHJ1Zw0KICBzdW1tYXJpc2UodG90YWxfcXVhbnRpdHlfNF95ZWFycyA9IHN1bShwYWlkX3F1YW50aXR5LCBuYS5ybSA9IFRSVUUpLCAgIyBUb3RhbCBwcmVzY3JpcHRpb25zIG92ZXIgNCB5ZWFycw0KICAgIGF2Z19hbm51YWxfdG90YWxfcXVhbnRpdHkgPSB0b3RhbF9xdWFudGl0eV80X3llYXJzIC8gNCwgICMgYXZlcmFnZSBhbm51YWwgcHJlc2NyaXB0aW9ucw0KICAgIGhiX3BvcHVsYXRpb24gPSBmaXJzdChoYl9wb3B1bGF0aW9uKSwgIyBoYl9wb3B1bGF0aW9uIGlzIGNvbnNpc3RlbnQgd2l0aGluIGVhY2ggaGJfbmFtZQ0KICAgIC5ncm91cHMgPSAiZHJvcCIpICU+JSAjIHVuZ3JvdXAgZGF0YQ0KICBkcm9wX25hKGRydWcpICU+JSAjIHJlbW92ZSByb3dzIHdpdGggbm8gZHJ1ZyB2YWx1ZXMNCiAgbXV0YXRlKGF2Z19hbm51YWxfcHJlc2NfMTAwMDAwID0gYXZnX2FubnVhbF90b3RhbF9xdWFudGl0eSAqIDEwMDAwMCAvIGhiX3BvcHVsYXRpb24pICU+JSAjIGF2ZXJhZ2UgYW5udWFsIHJhdGUgb2YgcHJlc2NyaXB0aW9ucyBwZXIgMTAwLDAwMA0KICBzZWxlY3QoaGJfbmFtZSwgZHJ1ZywgYXZnX2FubnVhbF9wcmVzY18xMDAwMDAsIGhiX3BvcHVsYXRpb24pICU+JSAjIHNlbGVjdCBjb2x1bW5zIG9mIGludGVyZXN0IGJlZm9yZSBwaXZvdA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZHJ1ZywgdmFsdWVzX2Zyb20gPSBhdmdfYW5udWFsX3ByZXNjXzEwMDAwMCwgbmFtZXNfZ2x1ZSA9ICJ7ZHJ1Z31fcmF0ZSIpICU+JSAjIFJlbmFtZSBjb2x1bW5zIGZvciBjbGFyaXR5DQogIGNsZWFuX25hbWVzKCkgIyBjbGVhbiBjb2x1bW4gbmFtZXMgZm9sbG93aW5nIHBpdm90DQoNCiMgY2FsY3VsYXRlIHRvdGFsIEVDUCBwcmVzY3JpcHRpb24gcmF0ZSBwZXIgaGVhbHRoIGJvYXJkDQpFQ1BfYW51YWxfcmF0ZV9kYXRhIDwtIEVDUF9hbnVhbF9yYXRlX2RhdGEgJT4lIA0KICBtdXRhdGUodG90YWxfRUNQX3JhdGUgPSByb3dTdW1zKHNlbGVjdCguLCBsZXZvbm9yZ2VzdHJlbF9yYXRlLCB1bGlwcmlzdGFsX2FjZXRhdGVfcmF0ZSksIG5hLnJtID0gVFJVRSkpICU+JSAgI3N1bSByYXRlcyANCiAgYXJyYW5nZShkZXNjKHRvdGFsX0VDUF9yYXRlKSkgIyBhcnJhbmdlIGJ5IHRvdGFsIHJhdGUgaW4gZGVzY2VuZGluZyBvcmRlcg0KDQojY2FsY3VsYXRlIHBlcmNlbnRhZ2UgeW91bmcgcGVvcGxlIHBlciBoZWFsdGggYm9hcmQgDQpFQ1BfYW51YWxfcmF0ZV9kYXRhX2J1Y2tldHMgPC0gRUNQX2FudWFsX3JhdGVfZGF0YSAlPiUgDQogIGZ1bGxfam9pbihhZ2VfcG9wdWxhdGlvbl9kYXRhKSAlPiUgIyB0byBnZXQgdGhlIHBvcHVsYXRpb24gb2YgdGhvc2UgYWdlZCAxNi0zNCB5ZWFycyANCiAgZ3JvdXBfYnkoaGJfbmFtZSkgJT4lIA0KICBtdXRhdGUocHJvcF95b3VuZ19wcGxfaGIgPSBwb3BfaGJfMTZfMzQvaGJfcG9wdWxhdGlvbikgJT4lICMgY2FsY3VsYXRlIHByb3BvcnRpb24gb2YgeW91bmcgcGVvcGxlIGluIGVhY2ggaGVhbHRoIGJvYXJkIA0KICB1bmdyb3VwKCkNCg0KYW5udWFsX2F2Z19FQ1BfdGFibGUgPC0gRUNQX2FudWFsX3JhdGVfZGF0YV9idWNrZXRzICU+JSANCiAgc2VsZWN0KGhiX25hbWUsIGxldm9ub3JnZXN0cmVsX3JhdGUsIHVsaXByaXN0YWxfYWNldGF0ZV9yYXRlLCB0b3RhbF9FQ1BfcmF0ZSxwcm9wX3lvdW5nX3BwbF9oYikgJT4lICMgU2VsZWN0IHJlbGV2YW50IGNvbHVtbnMNCiAgZ3QoKSAlPiUgDQogIGNvbHNfbGFiZWwoaGJfbmFtZSA9ICJIZWFsdGggQm9hcmQiLA0KICAgICAgICAgICAgIHRvdGFsX0VDUF9yYXRlPSAiVG90YWwiLA0KICAgICAgICAgICAgIGxldm9ub3JnZXN0cmVsX3JhdGU9ICIgTGV2b25vcmdlc3RyZWwiLA0KICAgICAgICAgICAgIHVsaXByaXN0YWxfYWNldGF0ZV9yYXRlPSIgVWxpcHJpc3RhbCBBY2V0YXRlIiwNCiAgICAgICAgICAgICBwcm9wX3lvdW5nX3BwbF9oYiA9ICIlIEFnZWQgMTYtMzQgWWVhcnMiKSAlPiUgIyByZW5hbWUgY29sdW1ucyB0byBtYWtlIHJlYWRlci1mcmllbmRseQ0KICBmbXRfbnVtYmVyKGNvbHVtbnMgPSBjKGxldm9ub3JnZXN0cmVsX3JhdGUsIHVsaXByaXN0YWxfYWNldGF0ZV9yYXRlLCB0b3RhbF9FQ1BfcmF0ZSwgcHJvcF95b3VuZ19wcGxfaGIpLCBkZWNpbWFscyA9IDApICU+JSAjIG5vIGRlY2ltYWwgcG9pbnRzIGFzIGZhbHNlIGFjY3VyYWN5IGRldHJhY3RzIGZyb20gdGhlIG1lc3NhZ2UgaW4gdGhlIGRhdGENCiAgY29sc19hbGlnbihhbGlnbiA9ICJjZW50ZXIiLA0KICAgICAgICAgICAgIGNvbHVtbnMgPSBjKGxldm9ub3JnZXN0cmVsX3JhdGUsdWxpcHJpc3RhbF9hY2V0YXRlX3JhdGUsdG90YWxfRUNQX3JhdGUsIHByb3BfeW91bmdfcHBsX2hiKSkgJT4lICAjIGNlbnRyZSBjb2x1bW4gbmFtZXMNCiAgZ3JhbmRfc3VtbWFyeV9yb3dzKGNvbHVtbnMgPSBjKGxldm9ub3JnZXN0cmVsX3JhdGUsdWxpcHJpc3RhbF9hY2V0YXRlX3JhdGUsIHRvdGFsX0VDUF9yYXRlKSwNCiAgICAgICAgICAgICAgICAgICAgIGZucyA9IGxpc3QoIk92ZXJhbGwgQXZlcmFnZSIgPSB+bWVhbiguLCBuYS5ybSA9IFRSVUUpKSwNCiAgICAgICAgICAgICAgICAgICAgIGZtdCA9IGxpc3QofiBmbXRfbnVtYmVyKC4sIGRlY2ltYWxzID0gMCkpKSAlPiUgICAjIGFkZCBhbiBvdmVyYWxsIGF2ZXJhZ2Ugb2YgdGhlIHByZXNjcmlwdGlvbiByYXRlIGNvbHVtbnMNCiAgZm10X3BlcmNlbnQoY29sdW1ucyA9IHByb3BfeW91bmdfcHBsX2hiLCBkZWNpbWFscyA9IDApICU+JSAgIyBhZGQgcGVyY2VudGFnZSBzaWduDQogIHRhYl9oZWFkZXIodGl0bGUgPSBtZCgiKipBdmVyYWdlIEFubnVhbCBSYXRlIG9mIEVtZXJnZW5jeSBDb250cmFjZXB0aW9uIFByZXNjcmlwdGlvbnMgYnkgSGVhbHRoIEJvYXJkIGluIFNjb3RsYW5kLioqIiksDQogICAgICAgICAgICAgc3VidGl0bGUgPSBtZCgiUmF0ZSBwZXIgMTAwLDAwMCB3b21lbiwgZGVyaXZlZCBmcm9tIHRoZSBtZWFuIHByZXNjcmlwdGlvbiByYXRlcyBhY3Jvc3MgdGhlIHllYXJzIDIwMTkgdG8gMjAyMi4gSGVhbHRoIEJvYXJkcyBhcmUgcmFua2VkIGluIGRlc2NlbmRpbmcgb3JkZXIuIikpICU+JSAjIGFkZCBhIHRpdGxlIGFuZCBzdWJ0aXRsZTsgbWQoKSBhbGxvd3MgdGV4dCBmb3JtYXR0aW5nIGZyb20gbWFyayBkb3duIA0KICB0YWJfc3Bhbm5lcihsYWJlbCA9IG1kKCIqUHJlc2NyaXB0aW9uIHJhdGUgcGVyIDEwMCwwMDAgd29tZW4qIiksDQogICAgY29sdW1ucyA9IGMobGV2b25vcmdlc3RyZWxfcmF0ZSx1bGlwcmlzdGFsX2FjZXRhdGVfcmF0ZSwgdG90YWxfRUNQX3JhdGUpKSAlPiUgICAjIGFkZCBhIHRpdGxlIHRvIHByZXNjcmlwdGlvbiByYXRlIGNvbHVtbnMuDQogIHRhYl9zb3VyY2Vfbm90ZShtZCgiKkRhdGEgZnJvbSBQdWJsaWMgSGVhbHRoIFNjb3RsYW5kLiBBdmFpbGFibGUgZnJvbTogKGh0dHBzOi8vd3d3Lm9wZW5kYXRhLm5ocy5zY290L2RhdGFzZXQvcHJlc2NyaXB0aW9ucy1pbi10aGUtY29tbXVuaXR5KSoiKSkgJT4lIA0KICB0YWJfc3R1YmhlYWQobWQoIioqMjAxOS0yMDIyKioiKSkgJT4lIA0KICB0YWJfZm9vdG5vdGUoZm9vdG5vdGUgPSAiaW5jbHVkZXMgQ2FwaXRhbCBDaXR5LCBFZGluYnVyZ2giLA0KICAgIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGhiX25hbWUsIHJvd3MgPSAyKSklPiUgDQogIG9wdF9zdHlsaXplKHN0eWxlID0gNiwgY29sb3IgPSAiY3lhbiIpDQoNCmFubnVhbF9hdmdfRUNQX3RhYmxlDQpgYGANCg0Kd2VzdGVybiBpc2xlcyByZWxhdGl2ZWx5IGhpZ2ggdWxpIHByZXNjcmlwdGlvbiBjb21tcGFyZWQgdG8gbGV2byAtIGV4cGxvcmUgaWYgcHJlc2NyaWJpbmcgcHJhY3RpY2VzIHZhcnkgYnkgbG9jYXRpb24/DQoNCiMjIyBIb3cgZG9lcyBkZXByaXZhdGlvbiBvbiB0aGUgdHlwZSBvZiBlbWVyZ2VuY3kgY29udHJhY2VwdGl2ZSBwcmVzY3JpYmVkDQoNCkhvdyBkb2VzIGRlcHJpdmF0aW9uIGluZmx1ZW5jZSB0eXBlIG9mIGNvbnRyYWNlcHRpb24gcHJlc2NyaWJlZD8NCkkgd2FudGVkIHRvIGV4cGxvcmUgaWYgdGhlcmUgd2FzIGFueSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0eXBlIG9mIGNvbnRyYWNlcHRpb24gYmVpbmcgcHJlc2NyaWJlZCBhbmQgZGVwcml2YXRpb24uIFRvIGRvIHRoaXMgSSBtYWRlIGEgcmF0aW8gb2YgbGV2b25vZ2VzdHJlbCB0byB0b3RhbCBlbWVyZ2VuY3kgY29udHJhY2VwdGlvbiBwcmVzY3JpcHRpb25zLiANCg0KPiBBLyhBK0IpDQo+IFdoZXJlIEEgPSBMZXZvbm9nZXN0cmVsIChwcmVzY3JpYmVkIHdpdGhpbiAzIGRheXMgb2YgdW5wcm90ZWN0ZWQgc2V4KQ0KPiBCID0gVWxpcHJpc3RhbCBBY2V0YXRlIChwcmVzY3JpYmVkIHdpdGhpbiA1IGRheXMgb2YgdW5wcm90ZWN0ZWQgc2V4KQ0KDQpUaGlzIGlzIGltcG9ydGFudCB0byBpZGVudGlmeSBhbnkgdmFyaWF0aW9uIGluIHByZXNjcmliaW5nIHBhdHRlcm5zIGluIG1vcmUgZGVwcml2ZWQgYXJlYXMuIERpZmZlcmVuY2VzIG1heSBzdWdnZXN0IHBhdGllbnRzIGFjY2VzcyBoZWFsdGggc2VydmljZXMgbGF0ZXIsIHNvIGhhdmUgdG8gdXNlIFVsaXByaXN0YWwgQWNldGF0ZSwgb3IgdGhhdCBHUHMgb3IgUGhhcm1hY2lzdHMgaGF2ZSBkaWZmZXJlbmNlcyBpbiBwcmVzY3JpYmluZyBwcmVmZXJlbmNlcyBpbiBtb3JlIGRlcHJpdmVkIGFyZWFzLg0KDQpUbyBtZWFzdXJlIGRlcHJpdmF0aW9uIEkgaGF2ZSB1c2VkIHRoZSBTY290dGlzaCBJbmRleCBvZiBNdWx0aXBsZSBEZXByaXZhdGlvbi4gSSB0b29rIHRoZSBTSU1EIDIwMjB2MiBkYXRhc2V0IGZyb20gUHVibGljIEhlYWx0aCBTY290bGFuZCB3ZWJzaXRlIFthdmFpbGFibGUgZnJvbTogaHR0cHM6Ly93d3cub3BlbmRhdGEubmhzLnNjb3QvZ2wvZGF0YXNldC9zY290dGlzaC1pbmRleC1vZi1tdWx0aXBsZS1kZXByaXZhdGlvbi9yZXNvdXJjZS9hY2FkZTM5Ni04NDMwLTRiMzQtODk1YS1iM2U3NTdmYTM0NmUgXSBhcyB0aGlzIGRhdGFzZXQgY29udGFpbnMgU0lNRCBkZWNpbGUgd2VpZ2h0ZWQgcGVyIEhlYWx0aCBCb2FyZCBwb3B1bGF0aW9uLg0KDQpXaGVuIGludGVycHJldGluZyBTSU1EIGluIGRlY2lsZXMgcmFuayAxIGlzIGNvbnNpZGVyZWQgdGhlIG1vc3QgZGVwcml2ZWQsIGFuZCByYW5rIDEwIGlzIGxlYXN0IGRlcHJpdmVkLiANCg0KYGBge3J9DQojIHJlYWQgaW4gZGF0YXNldHM6DQoNClNJTUQgPC0gcmVhZF9jc3YoImh0dHBzOi8vd3d3Lm9wZW5kYXRhLm5ocy5zY290L2dsL2RhdGFzZXQvNzhkNDFmYTktMWE2Mi00ZjdiLTllZGItM2U4NTIyYTkzMzc4L3Jlc291cmNlL2FjYWRlMzk2LTg0MzAtNGIzNC04OTVhLWIzZTc1N2ZhMzQ2ZS9kb3dubG9hZC9zaW1kMjAyMHYyXzIyMDYyMDIwLmNzdiIpICU+JQ0KICBjbGVhbl9uYW1lcygpICU+JQ0KICBzZWxlY3QoZGF0YV96b25lLCBzaW1kMjAyMHYyaGJfZGVjaWxlKQ0KDQojIEkgY2hvc2UgdG8gdXNlIEdQIFByYWN0aWNlcyBhbmQgTGlzdCBzaXplcyBmcm9tIE9jdG9iZXIgMjAyMiwgYXMgdGhpcyB3YXMgdGhlIGNsb3Nlc3QgZGF0YXNldCBJIGNvdWxkIGZpbmQgd2hpY2ggY29ycmVsYXRlZCB3aXRoIHRoZSBmaW5hbCB5ZWFyIG9mIG15IHByZXNjcmlwdGlvbnMgZGF0c2V0DQpncF9hZGRyZXNzZXMgPC0gcmVhZF9jc3YoImh0dHBzOi8vd3d3Lm9wZW5kYXRhLm5ocy5zY290L2RhdGFzZXQvZjIzNjU1YzMtNmUyMy00MTAzLWE1MTEtYTgwZDk5OGFkYjkwL3Jlc291cmNlLzFhMTVjYjM0LWZjZjktNGQzZi1hZDYzLTFiYTNlNjc1ZmJlMi9kb3dubG9hZC9wcmFjdGljZV9jb250YWN0ZGV0YWlsc19vY3QyMDIyLW9wZW4tZGF0YS5jc3YiKSAlPiUNCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgc2VsZWN0KHByYWN0aWNlX2NvZGUsIGdwX3ByYWN0aWNlX25hbWUsIGRhdGFfem9uZSkNCg0KIyBDcmVhdGUgRUNQX0dQIGJ5IHVzaW5nIHRoZSBHUF9hZGRyZXNzZXMgZGF0YXNldCB0byBtYXAgdGhlIEdQIHByYWN0aWNlIGNvZGUgdG8gYSBkYXRhem9uZS4gSSB0aGVuIHVzZWQgdGhlIGNvbHVtbiBkYXRhem9uZSB0byBmdWxsX2pvaW4oKSB0aGUgU0lNRCBkYXRhc2V0IHRvIHRoZSBwcmVzY3JpcHRpb25zIGRhdGFzZXQuDQoNCkVDUF9HUCA8LSBFQ1Bfc2NyaXB0cyAlPiUNCiAgZmlsdGVyKCFncF9wcmFjdGljZSAlaW4lIGMoOTk5OTYsIDk5OTk3LCA5OTk5OCkpICU+JSAjIHJlbW92ZSBkdW1teSBHUCBwcmFjdGljZSBjb2RlcyBhcyB0aGV5IGRvIG5vdCBoYXZlIGEga25vd24gZ3AgcHJhY3RpY2UgY29kZSBzbyBjYW5ub3QgYmUgbWFwcGVkIHRvIGEgU0lNRC4NCiAgbGVmdF9qb2luKGdwX2FkZHJlc3NlcywgYnkgPSBjKCJncF9wcmFjdGljZSIgPSAicHJhY3RpY2VfY29kZSIpKSAlPiUNCiAgI2xlZnRfam9pbihkYXRhX3pvbmVzLCBieSA9ICJkYXRhX3pvbmUiKSAlPiUNCiAgbGVmdF9qb2luKFNJTUQsIGJ5ID0gImRhdGFfem9uZSIpICU+JQ0KICBkcm9wX25hKHNpbWQyMDIwdjJoYl9kZWNpbGUpICU+JSAjIG5lZWQgU0lNRCB2YWx1ZSB0byBtYWtlIGJhcmNoYXJ0DQogIGdyb3VwX2J5KGdwX3ByYWN0aWNlKSAlPiUgDQogIG11dGF0ZSh0b3RhbF9xdWFudGl0eV9wZXJfZ3AgPSBzdW0ocGFpZF9xdWFudGl0eSkpICU+JSANCiAgY2xlYW5fbmFtZXMoKQ0KDQojIGNhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIEdQcyBwZXIgaGVhbHRoIGJvYXJkIA0KdG9hbF9ub19HUF9wZXJfaGIgPC0gRUNQX0dQICU+JSANCiAgZmlsdGVyKCFncF9wcmFjdGljZSAlaW4lIGMoOTk5OTYsIDk5OTk3LCA5OTk5OCkpICU+JSAjIHJlbW92ZSBkdW1teSBHUCBwcmFjdGljZSBjb2RlcyBhcyB0aGV5IGRvIG5vdCBoYXZlIGEga25vd24gZ3AgcHJhY3RpY2UgY29kZSBzbyBjYW5ub3QgYmUgbWFwcGVkIHRvIGEgU0lNRC4NCiAgZ3JvdXBfYnkoaGJfbmFtZSkgJT4lDQogIHN1bW1hcmlzZSh1bmlxdWVfZ3BfY291bnRfcGVyX2hiID0gbl9kaXN0aW5jdChncF9wcmFjdGljZSkpDQoNCiMgY2FsY3VsYXRlIGF2ZXJhZ2UgcG9wdWxhdGlvbiBwZXIgR1AgaW4gYSBoZWFsdGggYm9hcmQgDQpwb3BfcGVyX2dwX2hiIDwtIHBvcHVsYXRpb25fZGF0YSAlPiUgDQogIGZ1bGxfam9pbih0b2FsX25vX0dQX3Blcl9oYikgJT4lIA0KICBtdXRhdGUoYXZnX3BvcF9wZXJfR1AgPSBoYl9wb3B1bGF0aW9uIC91bmlxdWVfZ3BfY291bnRfcGVyX2hiKQ0KDQojIGpvaW4gcG9wX3Blcl9ncF9oYiB0byBFQ1BfR1AgDQpFQ1BfcG9wX3Blcl9ncF9oYiA8LSBFQ1BfR1AgJT4lIA0KICBsZWZ0X2pvaW4ocG9wX3Blcl9ncF9oYikNCg0KIyBtYWtlIGJhciBjaGFydA0KRUNQX1NJTURfYmFyY2hhcnQgPC0gRUNQX3BvcF9wZXJfZ3BfaGIgJT4lDQogIGdyb3VwX2J5KHNpbWQyMDIwdjJoYl9kZWNpbGUsIGRydWcpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgcHJlc2NyaXB0aW9uc19oYl9ncCA9ICh0b3RhbF9xdWFudGl0eV9wZXJfZ3AgKjEwMDAwIC8gYXZnX3BvcF9wZXJfR1ApLCAjIHN1bW1hcmlzZSB0aGUgcHJlc2NyaXB0aW9ucyBwZXIgMTAwLDAwMA0KICAgIC5ncm91cHMgPSAiZHJvcCIgICMgVW5ncm91cCBkYXRhIGFmdGVyIHN1bW1hcmlzYXRpb24NCiAgKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gcHJlc2NyaXB0aW9uc19oYl9ncCwgeSA9IGZhY3RvcihzaW1kMjAyMHYyaGJfZGVjaWxlLCBsZXZlbHMgPSAxOjEwKSwgZmlsbCA9IGRydWcpKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiLCBuYW1lID0gIkRydWcgVHlwZSIpICsgICMgYWRkIGNvbG91ciBwYWxldHRlDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmFyY2hhcnQgdG8gc2hvdyBob3cgdGhlIHByZXNjcmlwdGlvbiByYXRlIG9mIFxuIEVtZXJnZW5jeSBDb250cmFjZXB0aXZlIFBpbGwgdmFyaWVzIGJ5IFNjb3R0aXNoIEluZGV4IG9mIE11bHRpcGxlIERlcHJpdmF0aW9uIiwNCiAgICBzdWJ0aXRsZSA9ICJUaGlzIGNoYXJ0IHNob3dzIHRoZSBhdmVyYWdlIHByZXNjcmlwdGlvbiByYXRlIG9mIEVDUCBwZXIgU0lNRCwgXG4gYWNjb3VudGluZyBmb3IgZGlmZmVyZW5jZXMgaW4gbnVtYmVyIG9mIEdQcyBpbiBlYWNoIFNJTUQuIiwNCiAgICB4ID0gIlByZXNjcmlwdGlvbnMgcGVyIDEwLDAwMCB3b21lbiIsDQogICAgeSA9ICJTSU1EIERlY2lsZSBcbiAoMSA9IE1vc3QgRGVwcml2ZWQsIDEwID0gTGVhc3QgRGVwcml2ZWQpIiwNCiAgICBmaWxsID0gIkRydWciKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgaGp1c3QgPSAwLjUpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkNCg0KRUNQX1NJTURfYmFyY2hhcnQgPC0gZ2dwbG90bHkoRUNQX1NJTURfYmFyY2hhcnQpDQpFQ1BfU0lNRF9iYXJjaGFydA0KYGBgDQoNClByZXNjcmliaW5nIGNob2ljZXMgdmFyeSBwZXIgcmVnaW9ucyANCg0KYGBge3J9DQojIGxvYWQgdGhlIE5IUyBIZWFsdGggYm9hcmQgU2hhcGVmaWxlIGRvd25sb2FkZWQgZnJvbSBsZWFybiBwYWdlDQpOSFNfaGVhbHRoYm9hcmRzIDwtIHN0X3JlYWQoaGVyZSgiZGF0YSIsICJOSFNfaGVhbHRoYm9hcmRzXzIwMTkuc2hwIikpICU+JSANCiAgbXV0YXRlKEhCTmFtZSA9IHBhc3RlKCJOSFMiLCBIQk5hbWUpKSAlPiUgIyBmb3JtYXQgdG8gbWF0Y2ggRUNQX3NjcmlwdHMgZGF0YXNldA0KICBjbGVhbl9uYW1lcygpDQoNCiMgY2FsY3VsYXRlIHRoZSByYXRpbyBvZiBMZXYgdG8gVWxpIHByZXNjcmliZWQgDQp2YXJpYXRpb25fRUNQX3ByZXNjcmliZWQgPC0gRUNQX3NjcmlwdHMgJT4lIA0KICBncm91cF9ieShoYl9uYW1lLGRydWcpICU+JSANCiAgIyBjYWxjdWxhdGUgdGhlIHRvdGFsIG9mIExldiBhbmQgVWxpIHByZXNjcmliZWQgcGVyIGhlYWx0aCBib2FyZA0KICBzdW1tYXJpc2UodG90YWxfZWFjaF9kcnVnX3R5cGUgPSBzdW0ocGFpZF9xdWFudGl0eSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGRyb3BfbmEoZHJ1ZykgJT4lIA0KICAjcGl2b3Rfd2lkZXIgdG8gbW92ZSBkcnVnIG5hbWVzIHRvIGNvbHVtbnMgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBkcnVnLCB2YWx1ZXNfZnJvbSA9IHRvdGFsX2VhY2hfZHJ1Z190eXBlKSAlPiUNCiAgY2xlYW5fbmFtZXMoKSAlPiUgIyBjb25zaXN0ZW5jeSANCiAgbXV0YXRlKGxldm9fdG9fdWxpX3JhdGlvID0gbGV2b25vcmdlc3RyZWwgLyAobGV2b25vcmdlc3RyZWwgKyB1bGlwcmlzdGFsX2FjZXRhdGUpKSAjIGNhbGN1bGF0ZSByYXRpbyANCg0KIyBKb2luIHNwYXRpYWwgZGF0YSB3aXRoIHZhcmlhdGlvbl9FQ1BfcHJlc2NyaWJlZA0KdmFyaWF0aW9uX0VDUF9wcmVzY3JpYmVkIDwtIE5IU19oZWFsdGhib2FyZHMgJT4lDQogIGxlZnRfam9pbih2YXJpYXRpb25fRUNQX3ByZXNjcmliZWQpDQoNCiNDcmVhdGUgbWFwIGluIGdncGxvdA0KbWFwX3ZhcmlhdGlvbl9FQ1BfcHJlc2NyaWJlZCA8LSB2YXJpYXRpb25fRUNQX3ByZXNjcmliZWQgJT4lDQogIGdncGxvdChhZXMoZmlsbCA9IGxldm9fdG9fdWxpX3JhdGlvKSkgKw0KICBnZW9tX3NmKHNpemUgPSAwLjEsIGNvbG91ciA9ICJncmV5NTAiLCBhbHBoYSA9MC45KSArDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAiQmx1ZXMiLCBkaXJlY3Rpb24gPSAxKSArDQogIGxhYnModGl0bGUgPSAiR2VvZ3JhcGhpY2FsIHZhcmlhdGlvbiBpbiBFbWVyZ2VuY3kgQ29udHJhY2VwdGl2ZSBQaWxsIFxuIHByZXNjcmliaW5nIGluIFNjb3RsYW5kLiIsIA0KICAgICAgIHN1YnRpdGxlID0gIkhlYXRtYXAgc2hvd2luZyBMZXZvbm9yZ2VzdHJlbCBwcmVzY3JpcHRpb25zIGFzIGEgcHJvcG9ydGlvbiBvZiB0b3RhbCBFbWVyZ2VuY3kgXG4gQ29udHJhY2VwdGl2ZSBQaWxsIChFQ1ApIHByZXNjcmlwdGlvbnMgYnkgSGVhbHRoIEJvYXJkIHJlZ2lvbiIsIA0KICAgICAgIGZpbGwgPSAiTGV2b25vcmdlc3RyZWwgdG8gRUNQIHJhdGlvIiwgY2FwdGlvbiA9ICJEYXRhIFNvdXJjZTogUHVibGljIEhlYWx0aCBTY290bGFuZCBQcmVzY3JpcHRpb25zIGluIHRoZSBDb21tdW5pdHksIDIwMTktMjAyMiIpICsNCiAgY29vcmRfc2YoKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDIyLCBoanVzdD0wLjUpLCANCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgaGp1c3Q9MC41KSwgDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGhqdXN0PTAuNSksDQogICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsDQogICAgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKw0KICBhbm5vdGF0aW9uX3NjYWxlKGxvY2F0aW9uID0gInRsIikgKw0KICBhbm5vdGF0aW9uX25vcnRoX2Fycm93KA0KICAgIGxvY2F0aW9uID0gInRsIiwgICAgDQogICAgcGFkX3kgPSB1bml0KDAuNSwgImluIiksICAgIA0KICAgIHN0eWxlID0gbm9ydGhfYXJyb3dfbmF1dGljYWwoZmlsbCA9IGMoImdyZXk0MCIsICJ3aGl0ZSIpLGxpbmVfY29sID0gImdyZXkyMCIpKQ0KDQptYXBfdmFyaWF0aW9uX0VDUF9wcmVzY3JpYmVkDQpgYGANCg0KDQpgYGB7cn0NCiMgY2FsY3VsYXRlIHRoZSByYXRpbyBvZiBMZXYgdG8gVWxpIHByZXNjcmliZWQgDQp2YXJpYXRpb25fRUNQX3ByZXNjcmliZWRfdjIgPC0gRUNQX3NjcmlwdHMgJT4lIA0KICBncm91cF9ieShncF9wcmFjdGljZSxkcnVnKSAlPiUgDQogICMgY2FsY3VsYXRlIHRoZSB0b3RhbCBvZiBMZXYgYW5kIFVsaSBwcmVzY3JpYmVkIHBlciBoZWFsdGggYm9hcmQNCiAgc3VtbWFyaXNlKHRvdGFsX2VhY2hfZHJ1Z190eXBlID0gc3VtKHBhaWRfcXVhbnRpdHksIG5hLnJtID0gVFJVRSkpICU+JQ0KICBkcm9wX25hKGRydWcpICU+JSANCiAgI3Bpdm90X3dpZGVyIHRvIG1vdmUgZHJ1ZyBuYW1lcyB0byBjb2x1bW5zIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZHJ1ZywgdmFsdWVzX2Zyb20gPSB0b3RhbF9lYWNoX2RydWdfdHlwZSkgJT4lDQogIGNsZWFuX25hbWVzKCkgJT4lICMgY29uc2lzdGVuY3kgDQogIG11dGF0ZShsZXZvX3RvX3VsaV9yYXRpbyA9IGxldm9ub3JnZXN0cmVsIC8gKGxldm9ub3JnZXN0cmVsICsgdWxpcHJpc3RhbF9hY2V0YXRlKSkgJT4lICMgY2FsY3VsYXRlIHJhdGlvICU+JSANCiAgZHJvcF9uYShsZXZvX3RvX3VsaV9yYXRpbykgJT4lIA0KICBmdWxsX2pvaW4oRUNQX0dQKQ0KDQojIG1ha2UgYmFyIGNoYXJ0DQpFQ1BfU0lNRF9iYXJjaGFydF92YXJpYXRpb25zIDwtIHZhcmlhdGlvbl9FQ1BfcHJlc2NyaWJlZF92MiAlPiUNCiAgI2dyb3VwX2J5KHNpbWQyMDIwdjJoYl9kZWNpbGUsIGRydWcpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3Ioc2ltZDIwMjB2MmhiX2RlY2lsZSwgbGV2ZWxzID0gMToxMCksIHkgPSBsZXZvX3RvX3VsaV9yYXRpbywgZmlsbCA9IGRydWcpKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiLCBuYW1lID0gIkRydWcgVHlwZSIpICsgICMgYWRkIGNvbG91ciBwYWxldHRlDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVmFyaWF0aW9uIGluIHByZXNjcmliaW5nIHByYWN0aXNlIGJ5IFNJTUQiLA0KICAgIHN1YnRpdGxlID0gIiIsDQogICAgeCA9ICJTSU1EIERlY2lsZSBcbiAoMSA9IE1vc3QgRGVwcml2ZWQsIDEwID0gTGVhc3QgRGVwcml2ZWQpIiwNCiAgICB5ID0gInByZXNjcmlwdGlvbnMiLA0KICAgIGZpbGwgPSAiRHJ1ZyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBoanVzdCA9IDAuNSksDQogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KDQpFQ1BfU0lNRF9iYXJjaGFydF92YXJpYXRpb25zDQogIA0KYGBgDQoNCg0KIyMgQ29uY2x1c2lvbiANCg0KIyMjIFJlY29tbWVuZGF0aW9ucyBmcm9tIGFuYWx5c2lzIA0KDQojIyMgTGltaXRhdGlvbnMgb2YgdGhlIGRhdGFzZXQgYW5kIHN1Z2dlc3Rpb25zIGZvciBmdXR1cmUgYW5hbHlzaXMNCg0KDQoNCg0KIyMgUmVmZXJlbmNlcyANCkkgdXNlZCBodHRwczovL2dzdmVyaG9ldmVuLmdpdGh1Yi5pby9wb3N0L3pvdGVyby1ybWFya2Rvd24tY3NsLyB0byBzZXQgdXAgY2l0YXRpb25zLiBDaG9zZW4gQk1KIHN0eWxlIGFzIGNvbW1vbi4gDQoNCg==